package io.renren.config.security;

import com.alibaba.fastjson.JSON;
import io.renren.common.utils.R;
import io.renren.config.security.filter.CaptchaFilter;
import io.renren.config.security.provider.LoginProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@EnableWebSecurity(debug = false)
@EnableGlobalMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final LoginProvider loginProvider;
    private final CaptchaFilter captchaFilter;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 自定义service，自定义用户信息对象，结合数据库使用
//        auth.userDetailsService(sysUserService).passwordEncoder(new BCryptPasswordEncoder());

        // 设置自定义认证流程，Provider
        // 设置自定义provider,就不用设置service了，在provider中设置service
        auth.authenticationProvider(loginProvider);

    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers( "/login", "/logout","/config/**", "/","/static/**", "/*/static/**", "/captcha.jpg").permitAll()
                .anyRequest().authenticated()
                //配置访问路径对应权限规则（意思不使用在方法上添加注解，用数据库）
                .and()
                .formLogin()
                .successHandler((req, res, authentication) -> {
                    res.setContentType("application/json;charset=utf-8");
                    PrintWriter writer = res.getWriter();

                    writer.write(JSON.toJSONString(R.ok().put("token", "token888888888").put("expire", 3600 * 12)));
                    writer.flush();
                    writer.close();
                })
                .and()
                .logout()
                .logoutSuccessHandler((req, res, authentication) -> {
                    res.setContentType("application/json;charset=utf-8");
                    PrintWriter writer = res.getWriter();

                    writer.write(JSON.toJSONString(R.ok()));
                    writer.flush();
                    writer.close();
                });
        http.csrf().disable();

        http.addFilterBefore(captchaFilter, UsernamePasswordAuthenticationFilter.class);

        //🏚访问被拒绝的处理方法。
        //访问被拒绝分两种情况，一种是未登录：走authenticationEntryPoint。一种是登陆了但是无权限访问：走accessDeniedHandler

        //未登录，访问被拒绝，默认的authenticationEntryPoint逻辑为重定向到登陆页
        http.exceptionHandling().authenticationEntryPoint((HttpServletRequest req, HttpServletResponse res, AuthenticationException e) -> {
            res.setContentType("application/json;charset=utf-8");
            PrintWriter writer = res.getWriter();

            writer.write(JSON.toJSONString(R.error(401, "请登录访问！")));
            writer.flush();
            writer.close();
        });

        http.exceptionHandling().accessDeniedHandler((HttpServletRequest req, HttpServletResponse res, AccessDeniedException e) -> {
            res.setContentType("application/json;charset=utf-8");
            PrintWriter writer = res.getWriter();

            writer.write(JSON.toJSONString(R.error(403, "没有权限，请联系管理员授权！")));
            writer.flush();
            writer.close();
        });



    }
}
